#ifndef KPEXTOPIMGF32C2FFT_H
#define KPEXTOPIMGF32C2FFT_H

#include "kpextVkContext.h"
#include "kpextBaseCompute.h"

namespace kpext {

class OpImgF32C2FFT : public BaseCompute{
public:
    explicit OpImgF32C2FFT(kpextVkContext * ctx);

    virtual ~OpImgF32C2FFT() override;

    /**
     * @brief  重新构建计算管线及相关资源
     * @param cols  输入二维图像的列数, 如果方向为行变换保证其为2的整数次方
     * @param rows  输入二维图像的行数, 如果方向为列变换保证其为2的整数次方
     * @param inbuf  输入缓冲，计算过程中缓冲中的数据可能被改变，也可能被用于存放计算结果 @ref whichOutput
     * @param buf  计算用的缓冲, 与输入缓冲大小一样，用于存放计算的中间值，也可能被用于存放计算结果 @ref whichOutput
     * @param cmdbuf 用于内部数据初始化操作的命令缓冲
     * @param dir  FFT方向， 0为每行进行FFT， 1为每列进行FFT
     * @param preMul 变换前乘以的固定缩放值， 一般用于逆变换 或 缩放输入值提高精度(例如 preMul = 1.0f / cols)
     * @param invert 是否进行逆变换
     */
    virtual void rebuild(int cols, int rows,
                         std::shared_ptr<BaseBuffer> inbuf,
                         std::shared_ptr<BaseBuffer> buf,
                         std::shared_ptr<CommandBuffer> cmdbuf,
                         uint32_t dir = 0,
                         float preMul = 1.0f,
                         bool invert = false
            );


    /**
     * @brief rebuild后判断哪个才是输出缓冲区
     * @param buf1  应传入rebuild的inbuf
     * @param buf2  应传入rebuild的buf
     * @return 返回rebuild后作为FFT输出结果的缓冲区， 失败返回nullptr
     */
    virtual std::shared_ptr<BaseBuffer> whichOutput(
            std::shared_ptr<BaseBuffer> buf1,
            std::shared_ptr<BaseBuffer> buf2
            );

    // IRecordCommands interface
    void record(const vk::CommandBuffer &commandBuffer) override;

protected:
    typedef struct {
        uint32_t cols;
        uint32_t rows;
        uint32_t iscoldir;      //是否按列进行变换,0:每行数据进行变换 1:每列数据进行变换
        int32_t bitscount;      //进行变换的数据长度转为 2^N 的N-1值,这个值也是要进行的蝶形计算次数
        int32_t calcbufStarti;  //计算缓冲数组的索引起始值
        float alphaImag;    //在WkN虚部前相乘的数，可用于逆变换（=-1）
        float mulConst;     //蝶形变换后除以的常数，可用于使浮点数变小，以提高精度
        int32_t cyc;            //循环执行本计算着色器的次数
    } PushConstSZ;

    /**
     * @brief 计算着色器的work group size
     */
    std::array<uint32_t, 3> m_workGroupSize;

    /**
     * @brief 用于存放e^{-j\frac{2\pi k}{N}} 旋转因子的缓冲区
     */
    std::shared_ptr<UniformTexelBuffer> m_WkNBuf;

private:
    using BaseCompute::rebuild;

    /**
     * @brief 用于记录哪个才是输出缓冲区
     */
    BaseBuffer * m_outputBuf;
}; // class kpext::OpImgF32C2FFT

} // namespace kpext

#endif // KPEXTOPIMGF32C2FFT_H
